﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using DotNetNuke.Common.Utilities;
using DotNetNuke.Framework;
using DotNetNuke.Security;
using DotNetNuke.Security.Permissions;
using DotNetNuke.Services.Exceptions;
using DotNetNuke.Services.FileSystem;
using DotNetNuke.Services.Localization;
using HeroldIT.Dnn.JQuery;
using FileInfo = System.IO.FileInfo;
using Image = System.Drawing.Image;

namespace HeroldIT.Dnn.Modules.CodeBehind
{
    /// <summary>
    /// The code behind for the file browser's page.
    /// </summary>
    public class FileBrowser : PageBase
    {
        #region constants

        /// <summary>
        /// Defines the extensions for allowed image files.
        /// </summary>
        protected static readonly string[] ImageFileExtensions = new[]
                                                                     {
                                                                         "bmp",
                                                                         "gif",
                                                                         "jpe",
                                                                         "jpeg",
                                                                         "jpg",
                                                                         "png"
                                                                     };

        #endregion

        #region static methods

        /// <summary>
        /// Ensures that the given string <paramref name="s"/> ends with a slash.
        /// </summary>
        /// <param name="s">The string to check.</param>
        /// <returns>The given string <paramref name="s"/> with a trailing slash.</returns>
        protected static string EnsureTrailingSlash(string s)
        {
            if (!s.EndsWith("/", StringComparison.Ordinal))
            {
                return s + "/";
            }
            return s;
        }

        /// <summary>
        /// Checks whether the given <paramref name="extension"/> is a valid image type.
        /// </summary>
        /// <param name="extension">The extension to check.</param>
        /// <returns><c>true</c> if the extension is a valid image type, otherwise <c>false</c>.</returns>
        protected static bool IsImage(string extension)
        {
            return Array.BinarySearch(ImageFileExtensions, extension, CaseInsensitiveComparer.DefaultInvariant) >= 0;
        }

        #endregion

        #region control fields

        /// <summary>
        /// Holds the <see cref="ScriptManager"/> control for the page.
        /// </summary>
        protected ScriptManager scriptManager;

        /// <summary>
        /// Holds the upload file button control.
        /// </summary>
        protected Button btnUploadFile;

        /// <summary>
        /// Holds the current folder label.
        /// </summary>
        protected ITextControl lblCurrentFolder;

        /// <summary>
        /// Holds the selected file label.
        /// </summary>
        protected ITextControl lblSelectedFile;

        /// <summary>
        /// Holds the Ok button.
        /// </summary>
        protected IButtonControl btnOk;

        /// <summary>
        /// Holds the create folder button.
        /// </summary>
        protected IButtonControl btnCreateFolder;

        /// <summary>
        /// Holds the checkbox for overwriting existing files.
        /// </summary>
        protected CheckBox chkOverwriteExistingFile;

        /// <summary>
        /// Holds the current folder text control.
        /// </summary>
        protected ITextControl txtCurrentFolder;

        /// <summary>
        /// Holds the <see cref="UpdatePanel"/> containing the current folder label.
        /// </summary>
        protected UpdatePanel updCurrentFolder;

        /// <summary>
        /// Holds the <see cref="UpdatePanel"/> containing the creation controls.
        /// </summary>
        protected UpdatePanel updCreation;

        /// <summary>
        /// Holds the <see cref="PlaceHolder"/> containing the creation controls.
        /// </summary>
        protected PlaceHolder plhCreation;

        /// <summary>
        /// Holds the <see cref="UpdatePanel"/> containing the files.
        /// </summary>
        protected UpdatePanel updFiles;

        /// <summary>
        /// Holds the <see cref="Repeater"/> for displaying the folders.
        /// </summary>
        protected Repeater rptFolders;

        /// <summary>
        /// Holds the <see cref="Repeater"/> for displaying the files.
        /// </summary>
        protected Repeater rptFiles;

        /// <summary>
        /// Holds the message label.
        /// </summary>
        protected Label lblMessage;

        /// <summary>
        /// Holds the message table row.
        /// </summary>
        protected Control trMessage;

        /// <summary>
        /// Holds the <see cref="UpdatePanel"/> containing the message controls.
        /// </summary>
        protected UpdatePanel updMessage;

        /// <summary>
        /// Holds the new folder textbox.
        /// </summary>
        protected ITextControl txtFolderName;

        /// <summary>
        /// Holds the file upload control.
        /// </summary>
        protected FileUpload uplNewFile;

        /// <summary>
        /// Holds the selected file button.
        /// </summary>
        protected IButtonControl btnSelectedFile;

        /// <summary>
        /// Holds the <see cref="UpdatePanel"/> containing the selected file controls.
        /// </summary>
        protected UpdatePanel updSelectedFile;

        #endregion

        #region properties

        #region helpers

        private bool? hasWriteAccess;

        /// <summary>
        /// Gets whether the current user has write access to the current path.
        /// </summary>
        protected bool HasWriteAccess
        {
            get
            {
                string folder = EnsureTrailingSlash(this.ResolvePath().Substring(this.PortalSettings.HomeDirectoryMapPath.Length).Replace(
                    '\\', '/'));
                if (folder.Equals("/"))
                {
                    folder = String.Empty;
                }
                if (!this.hasWriteAccess.HasValue)
                {
                    string roles = FileSystemUtils.GetRoles(folder, this.PortalSettings.PortalId, "WRITE");
                    this.hasWriteAccess = PortalSecurity.IsInRoles(roles); // || PortalSecurity.IsInRole(this.PortalSettings.AdministratorRoleName);
                }
                return this.hasWriteAccess.Value;
            }
        }

        private bool? hasReadAccess;

        /// <summary>
        /// Gets whether the current user has read access to the current path.
        /// </summary>
        protected bool HasReadAccess
        {
            get
            {
                string folder = EnsureTrailingSlash(this.ResolvePath().Substring(this.PortalSettings.HomeDirectoryMapPath.Length).Replace(
                    '\\', '/'));
                if (folder.Equals("/"))
                {
                    folder = String.Empty;
                }
                if (!this.hasReadAccess.HasValue)
                {
                    string roles = FileSystemUtils.GetRoles(folder, this.PortalSettings.PortalId, "READ");
                    this.hasReadAccess = PortalSecurity.IsInRoles(roles); // || PortalSecurity.IsInRole(this.PortalSettings.AdministratorRoleName);
                }
                return this.hasReadAccess.Value;
            }
        }

        #endregion

        #region settings

        private string pageTitle = "Browse for file";

        /// <summary>
        /// Gets or sets the page title.
        /// </summary>
        protected string PageTitle
        {
            get { return this.pageTitle; }
            set { this.pageTitle = value; }
        }

        private string rootFolder = "";

        /// <summary>
        /// Gets or sets the root folder.
        /// </summary>
        protected string RootFolder
        {
            get { return this.rootFolder ?? String.Empty; }
            set { this.rootFolder = value; }
        }

        /// <summary>
        /// Gets or sets the current folder.
        /// </summary>
        protected string CurrentFolder
        {
            get
            {
                string currentFolder = this.ViewState["fbcurrentfolder"] as string;
                if (null == currentFolder)
                {
                    currentFolder = this.Request.Params["fbcurrentfolder"];
                    if (String.IsNullOrEmpty(currentFolder) || null == this.ResolvePath(currentFolder))
                    {
                        this.ViewState["fbcurrentfolder"] = "";
                        return "";
                    }
                    this.ViewState["fbcurrentfolder"] = currentFolder;
                }
                return currentFolder;
            }
            set
            {
                this.ViewState["fbcurrentfolder"] =
                    value.Replace('\\', '/').Trim(' ', '\t', '\r', '\n', '\f', '/').Replace("../", "").Replace("./", "");
            }
        }

        /// <summary>
        /// Gets or sets the current file.
        /// </summary>
        protected string CurrentFile
        {
            get
            {
                string currentFile = this.ViewState["fbcurrentfile"] as string;
                if (null == currentFile)
                {
                    currentFile = this.Request.Params["fbcurrentfile"];
                    if (String.IsNullOrEmpty(currentFile))
                    {
                        this.ViewState["fbcurrentfile"] = "";
                        return "";
                    }
                    if (currentFile[0] == '/')
                    {
                        currentFile = currentFile.Substring(1);
                    }
                    this.ViewState["fbcurrentfile"] = currentFile;
                }
                return currentFile;
            }
            set { this.ViewState["fbcurrentfile"] = value; }
        }

        private bool showFolders = true;

        /// <summary>
        /// Gets or sets whether to show folders.
        /// </summary>
        protected bool ShowFolders
        {
            get { return this.showFolders; }
            set { this.showFolders = value; }
        }

        private readonly List<string> filters = new List<string>();

        /// <summary>
        /// Gets the current file type filters.
        /// </summary>
        protected List<string> Filters
        {
            get { return this.filters; }
        }

        /// <summary>
        /// Gets or sets the maximum image width for uploaded images.
        /// </summary>
        protected int MaxImageWidth { get; set; }

        /// <summary>
        /// Gets or sets the maximum image height for uploaded images.
        /// </summary>
        protected int MaxImageHeight { get; set; }

        private int imageQuality = 85;

        /// <summary>
        /// Gets or sets the image quality for scaled uploaded images.
        /// </summary>
        protected int ImageQuality
        {
            get { return this.imageQuality; }
            set { this.imageQuality = value; }
        }

        private Color matteColor = Color.White;

        /// <summary>
        /// Gets or sets the matte color for scaled uploaded images.
        /// </summary>
        protected Color MatteColor
        {
            get { return this.matteColor; }
            set { this.matteColor = value; }
        }

        #endregion

        #endregion

        #region page lifecycle

        /// <summary>
        /// Raises the <see cref="E:System.Web.UI.Control.Init"/> event to initialize the page.
        /// </summary>
        /// <param name="e">An <see cref="T:System.EventArgs"/> that contains the event data.</param>
        protected override void OnInit(EventArgs e)
        {
            AJAX.RegisterScriptManager();
            this.RegisterJQuery();

            string fbTitle = this.Request.Params["fbtitle"];
            if (!String.IsNullOrEmpty(fbTitle))
            {
                this.PageTitle = fbTitle;
                //this.ClientScript.RegisterHiddenField("fbtitle", fbTitle);
            }
            this.Header.Title = HttpUtility.HtmlEncode(this.PageTitle);
            string fbRootFolder = this.Request.Params["fbrootfolder"];
            if (!String.IsNullOrEmpty(fbRootFolder))
            {
                this.RootFolder =
                    fbRootFolder.Replace('\\', '/').Trim(' ', '\t', '\r', '\n', '\f', '/').Replace("../", "").Replace(
                        "./", "");
                //this.ClientScript.RegisterHiddenField("fbrootfolder", this.RootFolder);
            }
            string fbShowFolders = this.Request.Params["fbshowfolders"];
            if (!String.IsNullOrEmpty(fbShowFolders))
            {
                try
                {
                    switch (fbShowFolders[0])
                    {
                        case '0':
                        case 'f':
                        case 'F':
                            this.ShowFolders = false;
                            break;

                        default:
                            this.ShowFolders = true;
                            break;
                    }
                    //this.ClientScript.RegisterHiddenField("fbshowfolders", fbShowFolders);
                }
                catch
                {
                }
            }
            string fbFilter = this.Request.Params["fbfilter"];
            if (!String.IsNullOrEmpty(fbFilter))
            {
                this.ParseFilter(fbFilter);
                //this.ClientScript.RegisterHiddenField("fbfilter", fbFilter);
            }
            else
            {
                this.ParseFilter(null);
            }
            string fbMaxImageWidth = this.Request.Params["fbmaximagewidth"];
            if (!String.IsNullOrEmpty(fbMaxImageWidth))
            {
                int width;
                if (int.TryParse(fbMaxImageWidth, NumberStyles.Integer, CultureInfo.InvariantCulture, out width))
                {
                    this.MaxImageWidth = Math.Max(0, width);
                }
            }
            string fbMaxImageHeight = this.Request.Params["fbmaximageheight"];
            if (!String.IsNullOrEmpty(fbMaxImageHeight))
            {
                int height;
                if (int.TryParse(fbMaxImageHeight, NumberStyles.Integer, CultureInfo.InvariantCulture, out height))
                {
                    this.MaxImageHeight = Math.Max(0, height);
                }
            }
            string fbImageQuality = this.Request.Params["fbimagequality"];
            if (!String.IsNullOrEmpty(fbImageQuality))
            {
                int quality;
                if (int.TryParse(fbImageQuality, NumberStyles.Integer, CultureInfo.InvariantCulture, out quality))
                {
                    this.ImageQuality = quality;
                }
            }
            string fbMatteColor = this.Request.Params["fbmattecolor"];
            if (!String.IsNullOrEmpty(fbMatteColor))
            {
                try
                {
                    this.MatteColor = ColorTranslator.FromHtml(fbMatteColor);
                }
                catch
                {
                }
            }
            this.scriptManager.RegisterPostBackControl(this.btnUploadFile);

            base.OnInit(e);
        }

        /// <summary>
        /// Raises the <see cref="E:System.Web.UI.Control.Load"/> event.
        /// </summary>
        /// <param name="e">The <see cref="T:System.EventArgs"/> object that contains the event data.</param>
        protected override void OnLoad(EventArgs e)
        {
            this.Localize();

            this.RefreshBindings();

            this.DataBind();

            base.OnLoad(e);
        }

        #endregion

        #region methods

        private void ResetAccessPermissions()
        {
            this.hasReadAccess = null;
            this.hasWriteAccess = null;
        }

        private void ParseFilter(string filter)
        {
            this.Filters.Clear();
            if (null != filter && filter.Equals("image"))
            {
                this.Filters.AddRange(ImageFileExtensions);
            }
            else if (!String.IsNullOrEmpty(filter))
            {
                this.Filters.AddRange(filter.Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries));
            }

            string fileExtensionsSetting = this.PortalSettings.HostSettings["FileExtensions"] as string;
            if (!String.IsNullOrEmpty(fileExtensionsSetting))
            {
                string[] fileExtensions = fileExtensionsSetting.Split(new[] {','},
                                                                      StringSplitOptions.RemoveEmptyEntries);
                if (fileExtensions.Length > 0)
                {
                    Array.Sort(fileExtensions);
                    if (this.Filters.Count <= 0)
                    {
                        this.Filters.AddRange(fileExtensions);
                    }
                    else
                    {
                        for (int i = this.Filters.Count - 1; i >= 0; i--)
                        {
                            string s = this.Filters[i];
                            if (Array.BinarySearch(fileExtensions, s, CaseInsensitiveComparer.DefaultInvariant) < 0)
                            {
                                this.Filters.RemoveAt(i);
                            }
                        }
                        this.Filters.Sort(
                            (s, s1) => String.Compare(s, s1, StringComparison.OrdinalIgnoreCase));
                        if (this.Filters.Count <= 0)
                        {
                            this.Filters.AddRange(fileExtensions);
                        }
                    }
                }
            }
        }

        /// <summary>
        /// Gets a localized resource for the given <paramref name="key"/>.
        /// </summary>
        /// <param name="key">The key to get the localized resource for.</param>
        /// <returns>The localized resource for the given <paramref name="key"/>.</returns>
        protected string GetString(string key)
        {
            return Localization.GetString(key, this.LocalResourceFile);
        }

        private void Localize()
        {
            if (null != this.lblCurrentFolder)
            {
                this.lblCurrentFolder.Text = this.GetString("lblCurrentFolder.Text");
            }
            if (null != this.lblSelectedFile)
            {
                this.lblSelectedFile.Text = this.GetString("lblSelectedFile.Text");
            }
            if (null != this.btnOk)
            {
                this.btnOk.Text = this.GetString("btnOk.Text");
            }
            if (null != this.btnUploadFile)
            {
                this.btnUploadFile.Text = this.GetString("btnUploadFile.Text");
            }
            if (null != this.btnCreateFolder)
            {
                this.btnCreateFolder.Text = this.GetString("btnCreateFolder.Text");
            }
            if (null != this.chkOverwriteExistingFile)
            {
                this.chkOverwriteExistingFile.Text = this.GetString("chkOverwriteExistingFile.Text");
            }
        }

        private void RefreshBindings()
        {
            if (null != this.btnSelectedFile)
            {
                this.btnSelectedFile.Text = String.IsNullOrEmpty(this.CurrentFile) ? String.Empty : "/" + this.CurrentFile;
            }
            if (null != this.txtCurrentFolder)
            {
                this.txtCurrentFolder.Text = "/" + this.CurrentFolder;
            }
            this.updCurrentFolder.Update();

            this.hasWriteAccess = null;
            this.plhCreation.Visible = this.HasWriteAccess;
            this.updCreation.Update();

            this.LoadFolders();
            this.LoadFiles();
            this.updFiles.Update();
        }

        /// <summary>
        /// Resolves the url to the current folder.
        /// </summary>
        /// <returns>The url to the current folder.</returns>
        protected string ResolveUrl()
        {
            string url = this.PortalSettings.HomeDirectory;
            if (!String.IsNullOrEmpty(this.RootFolder))
            {
                url = VirtualPathUtility.Combine(url, EnsureTrailingSlash(this.RootFolder));
            }
            if (!String.IsNullOrEmpty(this.CurrentFolder))
            {
                url = VirtualPathUtility.Combine(url, EnsureTrailingSlash(this.CurrentFolder + "/"));
            }
            return VirtualPathUtility.ToAbsolute(url);
        }

        /// <summary>
        /// Resolves the path to the given <paramref name="relativeFolder"/>.
        /// </summary>
        /// <param name="relativeFolder">The folder to resolve the path to.</param>
        /// <returns>The path to the given <paramref name="relativeFolder"/>, or <c>null</c> if the folder does not exist.</returns>
        protected string ResolvePath(string relativeFolder)
        {
            string rootPath = Path.Combine(this.PortalSettings.HomeDirectoryMapPath, this.RootFolder);
            string path = Path.Combine(rootPath, relativeFolder);
            return Directory.Exists(path) ? path : null;
        }

        /// <summary>
        /// Resolves the path to the current folder.
        /// </summary>
        /// <returns>The path to the current folder, or the root path if the folder does not exist.</returns>
        protected string ResolvePath()
        {
            string rootPath = Path.Combine(this.PortalSettings.HomeDirectoryMapPath, this.RootFolder);
            string path = Path.Combine(rootPath, this.CurrentFolder);
            return Directory.Exists(path) ? path : rootPath;
        }

        private void LoadFolders()
        {
            if (this.ShowFolders)
            {
                string path = this.ResolvePath();
                if (Directory.Exists(path))
                {
                    DirectoryInfo dirInfo = new DirectoryInfo(path);
                    DirectoryInfo[] dirInfos = dirInfo.GetDirectories();
                    List<string> directories = new List<string>();
                    if (!String.IsNullOrEmpty(this.CurrentFolder))
                    {
                        directories.Add("..");
                    }
                    if (this.HasReadAccess)
                    {
                        foreach (DirectoryInfo info in dirInfos)
                        {
                            if ((info.Attributes & FileAttributes.Hidden) == 0)
                            {
                                string roles = FileSystemUtils.GetRoles(
                                    info.FullName
                                        .Substring(this.PortalSettings.HomeDirectoryMapPath.Length)
                                        .Replace('\\', '/')
                                    + "/", this.PortalSettings.PortalId, "READ");
                                if (PortalSecurity.IsInRoles(roles))
                                    // || PortalSecurity.IsInRole(this.PortalSettings.AdministratorRoleName))
                                {
                                    directories.Add(info.Name);
                                }
                            }
                        }
                    }
                    this.rptFolders.DataSource = directories;
                    this.rptFolders.DataBind();
                }
            }
        }

        private void LoadFiles()
        {
            if (this.HasReadAccess)
            {
                string path = this.ResolvePath();
                if (Directory.Exists(path))
                {
                    DirectoryInfo dirInfo = new DirectoryInfo(path);
                    FileInfo[] fileInfos = dirInfo.GetFiles();
                    List<string> files = new List<string>();
                    foreach (FileInfo info in fileInfos)
                    {
                        if ((info.Attributes & FileAttributes.Hidden) == 0)
                        {
                            string extension = info.Extension;
                            FileInfo fileInfo = info;
                            if (this.Filters.Count <= 0
                                || (!String.IsNullOrEmpty(extension)
                                && this.Filters.Any(f => f.Equals(
                                    fileInfo.Extension.Substring(1),
                                    StringComparison.OrdinalIgnoreCase))))
                            {
                                files.Add(info.Name);
                            }
                        }
                    }
                    this.rptFiles.DataSource = files;
                    this.rptFiles.DataBind();
                }
            }
        }

        /// <summary>
        /// Generates the image url to the given <paramref name="fileName"/>.
        /// </summary>
        /// <param name="fileName">The file to which to generate the url.</param>
        /// <returns>The url to the image, or a default url, if the file is not an image.</returns>
        protected string GenerateImageUrl(string fileName)
        {
            foreach (string imageFileExtension in ImageFileExtensions)
            {
                if (fileName.EndsWith("." + imageFileExtension, StringComparison.OrdinalIgnoreCase))
                {
                    return VirtualPathUtility.Combine(this.ResolveUrl(), fileName);
                }
            }
            return this.ResolveUrl("images/write_48.png");
        }

        /// <summary>
        /// Gets the selected file's name without folder information.
        /// </summary>
        /// <returns>The selected file's name without folder information.</returns>
        protected string GetSelectedFileName()
        {
            string fileName = this.CurrentFile;
            int index = this.CurrentFile.LastIndexOf('/');
            if (index > 0)
            {
                fileName = this.CurrentFile.Substring(index + 1);
            }
            return fileName;
        }

        /// <summary>
        /// Gets the selected file's folder information.
        /// </summary>
        /// <returns>The selected file's folder information.</returns>
        protected string GetSelectedFileFolder()
        {
            string folderName = "";
            int index = this.CurrentFile.LastIndexOf('/');
            if (index > 0)
            {
                folderName = this.CurrentFile.Substring(0, index);
            }
            return folderName;
        }

        /// <summary>
        /// Gets whether the given <paramref name="fileName"/> is the selected file.
        /// </summary>
        /// <param name="fileName">The filename to check.</param>
        /// <returns><c>true</c> if the given <paramref name="fileName"/> is the currently selected file, otherwise <c>false</c>.</returns>
        protected bool IsFileSelected(string fileName)
        {
            return this.CurrentFolder.Equals(this.GetSelectedFileFolder()) &&
                   this.GetSelectedFileName().Equals(fileName);
        }

        private void ShowMessage(string message, bool isError)
        {
            this.lblMessage.Text = message;
            this.lblMessage.CssClass = isError ? "file-browser-message-error" : "file-browser-message";
            string script = "jQuery(function(){jQuery('#" + this.trMessage.ClientID +
                            "').css('display', '');jQuery('#" + this.lblMessage.ClientID +
                            "').css('display', 'none').slideDown('normal', fixHeight).prepend(jQuery('<div />').addClass('file-browser-message-close').html('&times;').click(function(){jQuery('#" +
                            this.lblMessage.ClientID + "').slideUp('normal', fixHeight)}))});";
            if (this.IsAsync)
            {
                ScriptManager.RegisterClientScriptBlock(this, typeof (FileBrowser), "showMessage", script, true);
            }
            else
            {
                this.ClientScript.RegisterClientScriptBlock(typeof (FileBrowser), "showMessage", script, true);
            }
            this.updMessage.Update();
        }

        #endregion

        #region event handlers

        /// <summary>
        /// Handles the create folder button's click event.
        /// </summary>
        /// <param name="sender">The event's sender.</param>
        /// <param name="e">The arguments passed to the event.</param>
        protected void btnCreateFolder_Click(object sender, EventArgs e)
        {
            if (this.HasWriteAccess)
            {
                string folderName = this.txtFolderName.Text;
                string parentPath = this.ResolvePath();
                string path = Path.Combine(parentPath, folderName);
                if (!Directory.Exists(path))
                {
                    try
                    {
                        FileSystemUtils.AddFolder(this.PortalSettings, parentPath, folderName);
                        string parentFolder = EnsureTrailingSlash((this.RootFolder ?? String.Empty) + this.CurrentFolder);
                        string newFolder = EnsureTrailingSlash(parentFolder + folderName);
                        FolderInfo folder = new FolderController().GetFolder(this.PortalSettings.PortalId, newFolder, false);
                        FolderPermissionController controller = new FolderPermissionController();
                        FolderPermissionCollection folderPermissions = controller.GetFolderPermissionsCollectionByFolderPath(this.PortalSettings.PortalId, parentFolder);
                        foreach (FolderPermissionInfo folderPermissionInfo in folderPermissions)
                        {
                            FileSystemUtils.SetFolderPermission(this.PortalSettings.PortalId, folder.FolderID, folderPermissionInfo.PermissionID, folderPermissionInfo.RoleID, newFolder);
                        }
                        this.txtFolderName.Text = String.Empty;
                        string message = String.Format(CultureInfo.CurrentCulture,
                                                       this.GetString("strDirectoryCreated.Format"), folderName);
                        this.ShowMessage(message, false);
                    }
                    catch (Exception ex)
                    {
                        Exceptions.LogException(ex);
                        string message = String.Format(CultureInfo.CurrentCulture,
                                                       this.GetString("strDirectoryCreateFailed.Format"), folderName,
                                                       ex.Message);
                        this.ShowMessage(message, true);
                        return;
                    }
                }
                if (!String.IsNullOrEmpty(this.CurrentFolder))
                {
                    this.CurrentFolder += "/" + folderName;
                }
                else
                {
                    this.CurrentFolder = folderName;
                }
                this.RefreshBindings();
            }
        }

        /// <summary>
        /// Handles the upload file button's click event.
        /// </summary>
        /// <param name="sender">The event's sender.</param>
        /// <param name="e">The arguments passed to the event.</param>
        protected void btnUploadFile_Click(object sender, EventArgs e)
        {
            if (this.uplNewFile.HasFile)
            {
                string fileName = Path.GetFileNameWithoutExtension(this.uplNewFile.FileName);
                string extension = Path.GetExtension(this.uplNewFile.FileName);
                if (extension.Length > 0)
                {
                    extension = extension.Substring(1);
                }
                string message;
                if (this.Filters.Count > 0
                    && !this.Filters.Exists(s => extension.Equals(s, StringComparison.OrdinalIgnoreCase)))
                {
                    message = String.Format(CultureInfo.CurrentUICulture,
                                            this.GetString("strFileTypeNotAllowed.Format"),
                                            extension);
                    this.ShowMessage(message, true);
                    return;
                }

                try
                {
                    string path = Path.Combine(this.ResolvePath(), this.uplNewFile.FileName);
                    if (File.Exists(path) && !this.chkOverwriteExistingFile.Checked)
                    {
                        message = String.Format(CultureInfo.CurrentUICulture,
                                                this.GetString("strUploadExists.Format"), this.uplNewFile.FileName);
                        this.ShowMessage(message, true);
                        return;
                    }

                    if (File.Exists(path))
                    {
                        File.Delete(path);
                    }
                    this.uplNewFile.PostedFile.SaveAs(path);

                    this.CurrentFile = (String.IsNullOrEmpty(this.CurrentFolder) ? "" : this.CurrentFolder + "/") +
                                       this.uplNewFile.FileName;
                    if (null != this.btnSelectedFile)
                    {
                        this.btnSelectedFile.Text = "/" + this.CurrentFile;
                    }
                    this.updSelectedFile.Update();

                    if ((this.MaxImageWidth > 0 || this.MaxImageHeight > 0) && IsImage(extension))
                    {
                        using (Image img = ImageHelper.FromFile(path))
                        {
                            if ((this.MaxImageWidth > 0 && img.Width > this.MaxImageWidth)
                                || (this.MaxImageHeight > 0 && img.Height > this.MaxImageHeight))
                            {
                                using (Image scaledImage =
                                    img.GetProportionallyScaledImage(this.MaxImageWidth > 0
                                                                         ? this.MaxImageWidth
                                                                         : int.MaxValue, this.MaxImageHeight > 0
                                                                                             ? this.MaxImageHeight
                                                                                             : int.MaxValue,
                                                                     this.MatteColor))
                                {
                                    int quality = Math.Max(Math.Min(this.ImageQuality, 100), 1);

                                    ImageCodecInfo jpegCodec = null;
                                    foreach (ImageCodecInfo ici in ImageCodecInfo.GetImageEncoders())
                                    {
                                        if (ici.FormatID.Equals(ImageFormat.Jpeg.Guid))
                                        {
                                            jpegCodec = ici;
                                            break;
                                        }
                                    }
                                    EncoderParameters eps =
                                        new EncoderParameters(1)
                                            {
                                                Param = new[]
                                                            {
                                                                new EncoderParameter(Encoder.Quality, quality)
                                                            }
                                            };
                                    string savePath = path;
                                    if (!extension.Equals("jpg", StringComparison.OrdinalIgnoreCase))
                                    {
                                        savePath = Path.Combine(this.ResolvePath(), fileName + ".jpg");
                                        File.Delete(path);

                                        this.CurrentFile = (String.IsNullOrEmpty(this.CurrentFolder)
                                                                ? ""
                                                                : this.CurrentFolder + "/") + fileName + ".jpg";
                                        if (null != this.btnSelectedFile)
                                        {
                                            this.btnSelectedFile.Text = "/" + this.CurrentFile;
                                        }
                                        this.updSelectedFile.Update();
                                    }

                                    scaledImage.Save(savePath, jpegCodec, eps);
                                }
                            }
                        }
                    }

                    message = String.Format(CultureInfo.CurrentUICulture, this.GetString("strUploadSuccess.Format"),
                                            this.uplNewFile.FileName);
                    this.ShowMessage(message, false);

                    this.RefreshBindings();
                }
                catch (Exception ex)
                {
                    Exceptions.LogException(ex);

                    message = String.Format(CultureInfo.CurrentUICulture, this.GetString("strUploadFailed.Format"),
                                            this.uplNewFile.FileName, ex.Message);
                    this.ShowMessage(message, true);
                }
            }
        }

        /// <summary>
        /// Handles the folder button's command event.
        /// </summary>
        /// <param name="sender">The event's sender.</param>
        /// <param name="e">The arguments passed to the event.</param>
        protected void btnFolder_Command(object sender, CommandEventArgs e)
        {
            string folderName = e.CommandArgument as string;
            if (!String.IsNullOrEmpty(folderName))
            {
                if (folderName.Equals(".."))
                {
                    int index = this.CurrentFolder.LastIndexOf('/');
                    this.CurrentFolder = index >= 0 ? this.CurrentFolder.Substring(0, index) : String.Empty;
                }
                else
                {
                    this.CurrentFolder = Path.Combine(this.CurrentFolder, folderName);
                }
                this.ResetAccessPermissions();
                this.RefreshBindings();
            }
        }

        /// <summary>
        /// Handles the file button's command event.
        /// </summary>
        /// <param name="sender">The event's sender.</param>
        /// <param name="e">The arguments passed to the event.</param>
        protected void btnFile_Command(object sender, CommandEventArgs e)
        {
            string fileName = e.CommandArgument as string;
            if (!String.IsNullOrEmpty(fileName))
            {
                this.CurrentFile = (String.IsNullOrEmpty(this.CurrentFolder) ? "" : this.CurrentFolder + "/") + fileName;
                this.RefreshBindings();
                this.updSelectedFile.Update();
            }
        }

        /// <summary>
        /// Handles the selected file button's click event.
        /// </summary>
        /// <param name="sender">The event's sender.</param>
        /// <param name="e">The arguments passed to the event.</param>
        protected void btnSelectedFile_Click(object sender, EventArgs e)
        {
            this.CurrentFolder = this.GetSelectedFileFolder();
            this.RefreshBindings();
        }

        #endregion
    }
}